package com.ctgu.tengyun.controller.file;

import com.ctgu.tengyun.bean.FileBean;
import com.ctgu.tengyun.bean.UploadFileResultBean;
import com.ctgu.tengyun.config.UploadConfig;
import com.ctgu.tengyun.exception.RequestValidateException;
import com.ctgu.tengyun.exception.TengyunRuntimeException;
import com.ctgu.tengyun.util.FileUtils;
import com.ctgu.tengyun.util.ServletFileUploadUtil;
import com.ctgu.tengyun.util.StringUtils;
import com.ctgu.tengyun.util.UploadUtil;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.UUID;

/**
 * Created by liaoweizhi on 2019/7/22.
 */
@RestController
@RequestMapping(value = "/v1/file/")
public class FileController {
    public static final Logger logger = LoggerFactory.getLogger(FileController.class);

    @Resource
    private UploadConfig uploadConfig;

    @PostMapping(value = "/upload")
    @ResponseBody
    public FileBean upload(HttpServletRequest request, @RequestParam("fileName") String fileName) {
        UploadFileResultBean fileResultBean = null;
        if (!ServletFileUpload.isMultipartContent(request)) {
            //无法识别的上传方式
            throw new RequestValidateException("not multipart content.", "not multipart content.");
        }

        if (null == fileName || fileName.split("\\.").length <= 1) {
            throw new RequestValidateException("file name is invalid", "file name is invalid");
        }

        File tmpStore = new File(uploadConfig.getBaseDir());
        UploadUtil.checkDirExist(tmpStore);
        ServletFileUpload upload = ServletFileUploadUtil.initServletFileUpload(tmpStore, uploadConfig.getFileSizeThreshold().intValue());
        FileItem uploadFileItem = ServletFileUploadUtil.parseFileItem(request, upload);
        if (uploadFileItem == null) {
            throw new RequestValidateException("no upload file", "no upload file");
        }
        try {
            fileResultBean = uploadFile(parseFormat(fileName), uploadFileItem, "cms", "objectId", null, true);
        } catch (Exception ex) {
            throw new TengyunRuntimeException("upload file to nfs error.."+ex.getMessage(), ex);
        } finally {
            //删除处理文件上传时生成的临时文件
            uploadFileItem.delete();
        }

        return new FileBean(fileName, fileResultBean.getStorePath());
    }

    public static String parseFormat(FileItem uploadFileItem) {
        String filename = uploadFileItem.getName();
        if (StringUtils.isEmpty(filename)) {
            throw new RequestValidateException("filename is null or empty.", "filename is null or empty.");
        }
        File f = new File(filename);
        filename = f.getName();
        String format = filename.substring(filename.lastIndexOf(".") + 1).toLowerCase();

        return format;
    }

    public static String[] parseFormat(String filename) {
        if (StringUtils.isEmpty(filename)) {
            throw new RequestValidateException("filename is null or empty.", "filename is null or empty.");
        }
        File f = new File(filename);
        filename = f.getName();
        String format = filename.substring(filename.lastIndexOf(".") + 1).toLowerCase();
        String preName = filename.substring(0, filename.lastIndexOf("."));

        return new String[]{preName, format};
    }

    /**
     * @param channel
     * @param objectId
     * @param timeLength         时长 gif图片属性
     * @param isGenerateWildcard 是否生成通配符jpg, png，需要生成通配符，git不需要通配符
     * @return
     */
    public UploadFileResultBean uploadFile(String[] fileName, FileItem fileItem, String channel, String objectId, Integer timeLength, boolean isGenerateWildcard) throws Exception {
        Date uploadTime = new Date();
        File tempStoragePath = new File(uploadConfig.getUtilUploadTmpDir());
        UploadUtil.checkDirExist(tempStoragePath);
        String uuid = UUID.randomUUID().toString();
        String tmpSavePath = UploadUtil.getTmpStorePath(uploadTime, uploadConfig.getTmpStoreDir(), uuid, fileName[1]);
        File tmpFile = new File(tmpSavePath);
        UploadUtil.checkParentDirExist(tmpFile);

        try {
            ServletFileUploadUtil.writeToFile(fileItem.getInputStream(), tmpSavePath);
        } catch (IOException e) {
            throw new TengyunRuntimeException("writeToFile error.", e);
        }

        String fileMd5 = FileUtils.getMd5ByFile(tmpFile);
        Long fileSize = tmpFile.length();
        String urlPath;
        urlPath = UploadUtil.getPath(channel, uploadTime, uuid, fileName[1], isGenerateWildcard);

        String storePath = UploadUtil.getStorePath(uploadConfig.getBaseDir(), channel, uploadTime, uuid, fileName[1], fileName[0]);
        try {
            File uploadFile = new File(storePath);
            org.apache.commons.io.FileUtils.moveFile(tmpFile, uploadFile);
        } catch (IOException e) {
            throw new TengyunRuntimeException("move file error. from:" + tmpFile.getAbsolutePath(), e);
        }

        if (tmpFile.exists() && !org.apache.commons.io.FileUtils.deleteQuietly(tmpFile)) {
            logger.warn("fail to delete tmpFile:{}", tmpSavePath);
        }

        return this.generateUploadFileResult(fileItem.getName(), channel, fileMd5, fileSize, fileName[1], storePath, uploadTime, urlPath, uuid, objectId, timeLength);
    }

    private UploadFileResultBean generateUploadFileResult(String realName, String channel, String fileMd5, Long fileSize, String format, String storagePath, Date uploadTime, String urlPath, String uuid, String objectId, Integer timeLength) {
        UploadFileResultBean uploadFileResultBean = new UploadFileResultBean();
        uploadFileResultBean.setRealName(realName);
        uploadFileResultBean.setChannel(channel);
        uploadFileResultBean.setFileMd5(fileMd5);
        uploadFileResultBean.setFileSize(fileSize);
        uploadFileResultBean.setFormat(format);
        uploadFileResultBean.setStorePath(storagePath);
        uploadFileResultBean.setUploadTime(uploadTime);
        uploadFileResultBean.setUrlPath(urlPath);
        uploadFileResultBean.setUuid(uuid);
        uploadFileResultBean.setObjectId(objectId);
        uploadFileResultBean.setTimeLength(timeLength);
        return uploadFileResultBean;
    }

}
